package com.chixing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chixing.entity.OrderChange;
import com.chixing.entity.OrderDetail;
import com.chixing.entity.Orders;
import com.chixing.entity.Roomtype;

import com.chixing.entity.VO.OrderVO;
import com.chixing.mapper.OrderChangeMapper;
import com.chixing.mapper.OrderDetailMapper;
import com.chixing.mapper.OrdersMapper;
import com.chixing.mapper.RoomtypeMapper;
import com.chixing.service.IOrderChangeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chixing.service.IRoomInventoryService;
import com.chixing.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author smith
 * @since 2025-09-30
 */
@Service
public class OrderChangeServiceImpl extends ServiceImpl<OrderChangeMapper, OrderChange> implements IOrderChangeService {

    @Autowired
    private RoomtypeMapper roomtypeMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderChangeMapper orderChangeMapper;
    @Autowired
    private IRoomInventoryService roomInventoryService;

    /**
     * 获取可调换的房型列表
     * @param hotelId 酒店ID
     * @param currentRoomTypeId 当前房型ID
     * @param checkIn 入住时间
     * @param checkOut 离店时间
     */

    @Override
    public Result getAvailableRoomTypes(Long hotelId, Long currentRoomTypeId, LocalDate checkIn, LocalDate checkOut) {
        try {
            // 1. 查询酒店所有房型（排除当前房型）
            QueryWrapper<Roomtype> queryWrapper = new QueryWrapper<>();
            queryWrapper.ne("roomtype_id", currentRoomTypeId);
            List<Roomtype> roomTypes = roomtypeMapper.selectList(queryWrapper);

            // 2. 筛选有库存的房型
            List<Roomtype> availableRooms = new ArrayList<>();
            for (Roomtype roomType : roomTypes) {
                // 检查该房型在入住期间是否有库存
                Result result = roomInventoryService.getRoomTypeRoomCount(
                        hotelId, roomType.getRoomtypeId(), checkOut);
                if (result.getCode() == 200) {
                    Integer count = (Integer) result.getData();
                    if (count != null && count > 0) {
                        availableRooms.add(roomType);
                    }
                }
            }
            return Result.getSuccess(availableRooms);
        }catch (Exception e){
            e.printStackTrace();
            return Result.getFail("获取可用房型失败");
        }


    }

    /**
     * 执行房型调换
     * @param orderId 订单ID
     * @param oldRoomTypeId 原房型ID
     * @param newRoomTypeId 新房型ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result changeRoomType(Long orderId, Long oldRoomTypeId, Long newRoomTypeId) {
        try {

    // 1. 验证订单状态（必须是已入住状态才能调换）
    Orders order = ordersMapper.selectById(orderId);
    if (order == null) {
        return Result.getFail("订单不存在");
    }
    if (!"已入住".equals(order.getOrderStatus())) {
        return Result.getFail("只有已入住订单才能调换房型");
    }

    // 2. 获取订单详情
    OrderDetail orderDetail = orderDetailMapper.selectOne(
            new QueryWrapper<OrderDetail>().eq("order_id", orderId));
    if (orderDetail == null) {
        return Result.getFail("订单详情不存在");
    }

    // 3. 获取新旧房型信息
    Roomtype oldRoomType = roomtypeMapper.selectById(oldRoomTypeId);
    Roomtype newRoomType = roomtypeMapper.selectById(newRoomTypeId);
    if (oldRoomType == null || newRoomType == null) {
        return Result.getFail("房型信息不存在");
    }

    // 4. 计算价格差
    BigDecimal priceDiff = newRoomType.getRoomtypePrice()
            .subtract(oldRoomType.getRoomtypePrice())
            .multiply(new BigDecimal(orderDetail.getRoomQuantity()));

    // 5. 释放原房型库存并锁定新房型库存
    // 5.1 释放原房型
    roomInventoryService.releaseBookedInventory(orderId);

    // 5.2 锁定新房型
    Result lockResult = roomInventoryService.decrCount(
            order.getHotelId(),
            Date.from(orderDetail.getCheckIn().atStartOfDay(ZoneId.systemDefault()).toInstant()),
            Date.from(orderDetail.getCheckOut().atStartOfDay(ZoneId.systemDefault()).toInstant()),
            newRoomTypeId
    );
    if (lockResult.getCode() != 200) {
//        throw new RuntimeException("新房型库存不足，无法调换");
        System.out.println("------------------------"+lockResult);
    }

    // 6. 更新订单详情中的房型ID
    orderDetail.setRoomtypeId(newRoomTypeId);
    orderDetailMapper.updateById(orderDetail);

    // 7. 记录房型调换记录
    OrderChange orderChange = new OrderChange();
    orderChange.setOrderId(orderId);
    orderChange.setOldRoomtypeId(oldRoomTypeId);
    orderChange.setNewRoomtypeId(newRoomTypeId);
    orderChange.setPriceDiff(priceDiff);
    orderChange.setChangeStatus("待支付");
    orderChange.setChangeTime(LocalDateTime.now());
    // 设置差价类型（补差价或退差价）
    orderChange.setType(priceDiff.compareTo(BigDecimal.ZERO) >= 0 ? "用户补差价" : "商家退款");
    orderChangeMapper.insert(orderChange);

            // ===================== 新增差价判断逻辑 =====================
            try {
                // 判断差价类型
                if (priceDiff.compareTo(BigDecimal.ZERO) > 0) {
                    // ---------------------- 用户需补差价 ----------------------
                    orderChange.setChangeStatus("待支付");
                    orderChangeMapper.updateById(orderChange);
                    System.out.println("房型调换需补差价：" + priceDiff + " 元，准备调用支付接口...");

                    // 封装支付所需信息给前端
                    OrderVO payVO = new OrderVO();
                    payVO.setOrderId(order.getOrderId());
                    payVO.setOrderNumber(order.getOrderNumber());
                    payVO.setOrderPrice(priceDiff); // 差价
                    payVO.setHotelName(newRoomType.getRoomtypeName()); // 显示标题
                    payVO.setRoomtypeId(newRoomTypeId);
                    payVO.setCheckIn(orderDetail.getCheckIn());
                    payVO.setCheckOut(orderDetail.getCheckOut());
                    payVO.setHotelId(order.getHotelId());

                    // 构造支付请求参数（与 /order-transactions 控制器匹配）
                    java.util.Map<String, Object> payBody = new java.util.HashMap<>();
                    payBody.put("orderId", order.getOrderId());
                    payBody.put("orderNumber", order.getOrderNumber());
                    payBody.put("orderPrice", priceDiff);
                    payBody.put("hotelName", "房型调换补差价");

                    org.springframework.web.client.RestTemplate restTemplate = new org.springframework.web.client.RestTemplate();
                    String payUrl = "http://localhost:8080/app/order-transactions"; // 根据你本地或服务器端口调整
                    String payResult  = restTemplate.postForObject(payUrl, payBody, String.class);


                    System.out.println("已发起支付宝支付请求（补差价）");
                    return Result.getSuccess("需补差价，请前往支付");

                } else if (priceDiff.compareTo(BigDecimal.ZERO) < 0) {
                    // ---------------------- 商家需退款 ----------------------
                    BigDecimal refundAmount = priceDiff.abs();
                    System.out.println("房型调换需退款：" + refundAmount + " 元，准备调用退款接口...");

                    // 构造退款请求参数（与 /refunds/refund 控制器匹配）
                    java.util.Map<String, Object> refundBody = new java.util.HashMap<>();
                    refundBody.put("orderId", order.getOrderId());
                    refundBody.put("orderNumber", order.getOrderNumber());
                    refundBody.put("refundAmount", refundAmount);
                    refundBody.put("refundReason", "房型调换退款");

                    org.springframework.web.client.RestTemplate restTemplate = new org.springframework.web.client.RestTemplate();
                    String refundUrl = "http://localhost:8080/app/refunds/refund"; // 根据你项目实际端口调整
                    String refundResult = restTemplate.postForObject(refundUrl, refundBody, String.class);

                    if (refundResult != null) {
                        // 退款成功：更新订单详情（实际完成房型调换）
                        orderDetail.setRoomtypeId(newRoomTypeId);
                        orderDetailMapper.updateById(orderDetail);

                        orderChange.setChangeStatus("已退款");
                        orderChangeMapper.updateById(orderChange);

                        return Result.getSuccess("房型调换完成，差价已退款");

                } else {
                    // ---------------------- 无需差价 ----------------------
                    orderChange.setChangeStatus("已完成");
                    orderChangeMapper.updateById(orderChange);
                    System.out.println("房型调换完成，无需补差价或退款");
                    return Result.getSuccess("房型调换成功，无需补差价");
                }
                    }
            } catch (Exception e) {
                e.printStackTrace();
                System.err.println("差价处理调用异常：" + e.getMessage());
            }

// ============================================================

            orderDetail.setRoomtypeId(newRoomTypeId);
            orderDetailMapper.updateById(orderDetail);

// 修改调换状态为已完成
            orderChange.setChangeStatus("已完成");
            orderChangeMapper.updateById(orderChange);

    return Result.getSuccess("房型调换成功");
        }catch (Exception e) {
            e.printStackTrace();
            return Result.getFail("房型调换失败：" + e.getMessage());
        }
    }
}
